package com.cloud.servicegreyrelease1.compoment.ribbonrule;

import com.cloud.servicegreyrelease1.compoment.threadlocal.UserIdThreadLocal;
import com.cloud.servicegreyrelease1.entity.GreySetting;
import com.cloud.servicegreyrelease1.entity.OnlineSetting;
import com.cloud.servicegreyrelease1.service.GreyService;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import com.netflix.niws.loadbalancer.DiscoveryEnabledServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;

@Component
@SuppressWarnings("all")
public class GreyRule extends AbstractLoadBalancerRule {

    @Autowired
    GreyService greyService;

    @Override
    public void initWithNiwsConfig(IClientConfig clientConfig) {

    }

    @Override
    public Server choose(Object key) {
        return choose(getLoadBalancer(),key);
    }

    private Server choose(ILoadBalancer lb, Object key){

        Server chooseServer = null;
        try {
            //获取从 切面传过来的用户Id
            Map<String, String> paramsMap = UserIdThreadLocal.get();
            //获取可用的服务列表
            List<Server> reachableServers = lb.getReachableServers();
            String userId = paramsMap.get("userId");
            //取其中的一个服务，拿到服务名称，来遍历数据库中服务的配置
            InstanceInfo serviceInfo = ((DiscoveryEnabledServer) reachableServers.get(0)).getInstanceInfo();
            String serviceName = serviceInfo.getAppName().toLowerCase(Locale.ROOT);
            //根据服务名称，获取服务的配置
            GreySetting greySetting = greyService.queryGreySetting(userId, serviceName);

            //如果有该服务的配置
            if (greySetting != null) {
                //通过 version 来过滤服务，这里主要是拿到灰度服务
                List<Server> serverList = reachableServers.stream().filter(server -> {
                    InstanceInfo instanceInfo = ((DiscoveryEnabledServer) server).getInstanceInfo();
                    String version = instanceInfo.getMetadata().get("version");
                    return greySetting.getVersion().equals(version);
                }).collect(Collectors.toList());
                if (serverList.size() > 0) {
                    chooseServer = serverList.get(ThreadLocalRandom.current().nextInt(serverList.size()));
                }
            }

            //如果该用户没有配置服务的灰度版本，那么要拿线上版本，也就是生产版本
            if (chooseServer == null) {
                OnlineSetting onlineSetting = greyService.queryOnLineSetting(serviceName);
                if (onlineSetting != null) {
                    List<Server> serverList = reachableServers.stream().filter(server -> {
                        InstanceInfo instanceInfo = ((DiscoveryEnabledServer) server).getInstanceInfo();
                        String version = instanceInfo.getMetadata().get("version");
                        return onlineSetting.getVersion().equals(version);
                    }).collect(Collectors.toList());
                    if (serverList.size() > 0) {
                        chooseServer = serverList.get(ThreadLocalRandom.current().nextInt(serverList.size()));
                    }
                }
            }

            //如果生产版本没有配置，那么就随机获取一个服务
            if (chooseServer == null) {
                chooseServer = reachableServers.get(ThreadLocalRandom.current().nextInt(reachableServers.size()));
            }
        }finally {
            UserIdThreadLocal.remove();
        }


        return chooseServer;
    }
}
